package com.zzh.demo.core.handler;

import com.github.pagehelper.Page;
import com.zzh.demo.core.model.ResponseModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * description: 对controller层返回值做统一处理，如分页查询对象统一封装，返回值类型统一转化等<br>
 * createTime: 2019/2/149:30 <br>
 *
 * @author zzh
 */
@ControllerAdvice
@ResponseBody
public class ReturnValueHandler implements ResponseBodyAdvice<Object> {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    private static final Set<Class> excludeSet = new HashSet<>();

    private static final List<String> exceludeUrl = new ArrayList<>();

    static {
        // Spring对String类型的返回值做了特殊处理，修改了返回值类型后将报错
        excludeSet.add(String.class);

        // Swagger-ui返回类型
        excludeSet.add(springfox.documentation.swagger.web.UiConfiguration.class);
        excludeSet.add(ResponseModel.class);

        exceludeUrl.add("/swagger-resources");
        exceludeUrl.add("/v2/api-docs");
    }

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        //TODO 待实现
        return true;
    }


    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        //非ResponseModel的String以外的类型的返回值，包装为ResponseModel类实例的data属性里

        try {
            String uri = request.getURI().getPath();
            logger.info("uri:" + uri + " return type: " + body.getClass());
            if(!excludeSet.contains(body.getClass()) && !isExcluded(uri)) {
                if(body instanceof Page) {
                    return new ResponseModel((Page) body);
                } else if(body instanceof List) {
                    return new ResponseModel((List) body);
                } else {
                    return ResponseModel.success(body);
                }
            }
        } catch (Exception e) {
            logger.info("包装返回类型异常" + e);
        }

        return body;
    }

    private boolean isExcluded(String uri) {
        for (String s : exceludeUrl) {
            if(uri.contains(s)) {
                return true;
            }
        }
        return false;
    }
}
